#include "const/oPreDefine.h"
#include "platform/oPlatformWorld.h"
#include "platform/oCamera.h"
using namespace platform;

oPlatformWorld::oPlatformWorld()
{ }

oPlatformWorld::~oPlatformWorld()
{
	_layers.clear();
}

void oPlatformWorld::addChild( CCNode * child )
{
	this->addChild(child, child->getZOrder(), child->getTag());
}

void oPlatformWorld::addChild( CCNode * child, int zOrder )
{
	this->addChild(child, zOrder, child->getTag());
}

void oPlatformWorld::addChild( CCNode *child, int zOrder, int tag )
{
	CCNode* layer = oPlatformWorld::getLayer(zOrder);
	layer->addChild(child, zOrder, tag);
}

void oPlatformWorld::setLayerRatio( int zOrder, const CCPoint& ratio )
{
	oLayer* layer = oPlatformWorld::getLayer(zOrder);
	layer->ratio = ratio;
}

const CCPoint& oPlatformWorld::getLayerRatio(int zOrder)
{
	oLayer* layer = oPlatformWorld::getLayer(zOrder);
	return layer->ratio;
}

oLayer* oPlatformWorld::getLayer( int zOrder )
{
	auto it = _layers.find(zOrder);
	if (it != _layers.end())
	{
		return it->second;
	}
	else
	{
		oLayer* newLayer = oLayer::node();
		_camera->addChild(newLayer, zOrder, newLayer->getTag());
		_layers[zOrder] = newLayer;
		return newLayer;
	}
}

bool oPlatformWorld::init()
{
	if (!oWorld::init())
	{
		return false;
	}
	_camera = oCamera::node();
	_camera->moved += oCameraHandler(&oPlatformWorld::onCameraMoved, this);
	CCNode::addChild(_camera, 0, 0);
	_layerUI = CCNode::node();
	CCNode::addChild(_layerUI, 0, 1);
	return true;
}

oCamera* oPlatformWorld::getCamera() const
{
	return _camera;
}

CCNode* oPlatformWorld::getUILayer() const
{
	return _layerUI;
}

void oPlatformWorld::onCameraMoved( float deltaX, float deltaY )
{
	BOOST_FOREACH(oLayerMap::value_type& it, _layers)
	{
		oLayer* layer = it.second;
		layer->setPositionX(deltaX * layer->ratio.x + layer->getPositionX());
		layer->setPositionY(deltaY * layer->ratio.y + layer->getPositionY());
	}
}

void oPlatformWorld::setLayerOffset( int zOrder, const CCPoint& offset )
{
	oLayer* layer = oPlatformWorld::getLayer(zOrder);
	layer->setOffset(offset);
}

const CCPoint& oPlatformWorld::getLayerOffset( int zOrder )
{
	oLayer* layer = oPlatformWorld::getLayer(zOrder);
	return layer->getOffset();
}

void oLayer::setOffset( const CCPoint& offset )
{
	float deltaX = CCNode::getPositionX() - _offset.x;
	float deltaY = CCNode::getPositionY() - _offset.y;
	CCNode::setPosition(deltaX + offset.x, deltaY + offset.y);
	_offset = offset;
}

const CCPoint& oLayer::getOffset() const
{
	return _offset;
}

CCAffineTransform oLayer::nodeToParentTransform()
{
	return CCAffineTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
}

oLayer* oLayer::node()
{
	oLayer* layer = new oLayer();
	layer->autorelease();
	return layer;
}

void oPlatformWorld::clearLayer( int zOrder )
{
	auto it = _layers.find(zOrder);
	if (it != _layers.end())
	{
		_camera->removeChild(it->second, true);
		_layers.erase(it);
	}
}

void oPlatformWorld::clearLayer()
{
	BOOST_FOREACH(const oLayerMap::value_type& item, _layers)
	{
		_camera->removeChild(item.second, true);
	}
	_layers.clear();
}
